package com.flying.flow.service;

import java.util.Date;

import com.flying.common.annotation.DaoCreate;
import com.flying.common.annotation.DaoQuery;
import com.flying.common.annotation.DaoRemove;
import com.flying.common.annotation.DaoUpdate;
import com.flying.common.util.DateUtils;
import com.flying.common.util.DateUtils.Field;
import com.flying.common.util.StringUtils;
import com.flying.flow.model.FlowInstance;
import com.flying.flow.model.Node;
import com.flying.flow.model.Node.NodeType;
import com.flying.flow.model.Node.TaskStartType;
import com.flying.flow.model.NodeInstance;
import com.flying.flow.model.NodeInstance.NodeInstanceStatus;
import com.flying.flow.util.FlowUtils;
import com.flying.framework.annotation.MethodInfo;
import com.flying.framework.annotation.Param;
import com.flying.framework.annotation.Service;
import com.flying.framework.context.ServiceContext;
import com.flying.framework.model.ActionResult;
import com.flying.framework.model.ModelFactory;
import com.flying.framework.model.QueryResult;
import com.flying.framework.security.Principal;
import com.flying.framework.service.AbstractService;

@Service(value="NodeInstanceService", desc="节点实例")
public class NodeInstanceService extends AbstractService{
	private FlowInstanceService fis;
	
	public void setFlowInstanceService(FlowInstanceService s) {
		this.fis = s;
	}
    
	@MethodInfo("新增")
	public NodeInstance createByNode(
			@Param(value=NodeInstance.PARTICIPANTS, required=false,	desc="执行人") String participants,
			@Param(value=NodeInstance.FLOW_INSTANCE_ID, required=true,	desc="流程实例ID") Long flow_instance_id,
			@Param(value=NodeInstance.NODE_ID, required=true,	desc="节点") Node n) throws Exception {
		FlowInstance fi = this.fis.findById(flow_instance_id);
		Date plan_start = new Date();
		Date plan_end = DateUtils.add(plan_start, Field.SECOND, FlowUtils.parseExpectTimeAsSeconds(n.getExpectTime()));
		Date actual_start = n.getTaskStartType() == TaskStartType.AUTO.value() && !StringUtils.isEmpty(participants) || n.getNodeType() == NodeType.START.value()?plan_start:null;
		return this.create(
				flow_instance_id, n.getNodeId(), n.getFlowDefId(), fi.getFlowId(), n.getName(), n.getRemarks(), fi.getBusinessCode(), fi.getOrderNo(),
				plan_start, plan_end, n.getExpectTime(), actual_start, null, n.getFormAction(), n.getFormCode(), n.getFormData(),
				n.getEmergencyLevel(), n.getPriorityLevel(), participants, null, null, null);
	}
        
	@MethodInfo("新增")
	@DaoCreate(entity=NodeInstance.ENTITY_NAME)
	public NodeInstance create(
			@Param(value=NodeInstance.FLOW_INSTANCE_ID, required=true,	desc="流程实例ID") Long flow_instance_id,
			@Param(value=NodeInstance.NODE_ID, required=true,	desc="节点ID") Long node_id,
			@Param(value=NodeInstance.FLOW_DEF_ID, required=true,	desc="流程定义ID") Long flow_def_id,
			@Param(value=NodeInstance.FLOW_ID, required=true,	desc="流程ID") Long flow_id,
			@Param(value=NodeInstance.NAME, required=true,	desc="名称") String name,
			@Param(value=NodeInstance.REMARKS, required=false,	desc="说明") String remarks,
			@Param(value=NodeInstance.BUSINESS_CODE, required=true,	desc="业务代码") String business_code,
			@Param(value=NodeInstance.ORDER_NO, required=false,	desc="工单号") String order_no,
			
			@Param(value=NodeInstance.PLAN_START, required=false,	desc="计划开始时间") Date plan_start,
			@Param(value=NodeInstance.PLAN_END, required=false,	desc="计划结束时间") Date plan_end,
			@Param(value=NodeInstance.EXPECT_TIME, required=false,	desc="期望完成时间") String expect_time,
			@Param(value=NodeInstance.ACTUAL_START, required=false,	desc="实际开始时间") Date actual_start,
			@Param(value=NodeInstance.ACTUAL_END, required=false,	desc="实际结束时间") Date actual_end,
			@Param(value=NodeInstance.FORM_ACTION, required=false,	desc="表单行为") String form_action,
			@Param(value=NodeInstance.FORM_CODE, required=false,	desc="表单代码") String form_code,
			@Param(value=NodeInstance.FORM_DATA, required=false,	desc="表单数据") String form_data,
			
			@Param(value=NodeInstance.EMERGENCY_LEVEL, required=false,	desc="紧急程度") Integer emergency_level,
			@Param(value=NodeInstance.PRIORITY_LEVEL, required=false,	desc="优先级别") Integer priority_level,
			@Param(value=NodeInstance.PARTICIPANTS, required=false,	desc="执行人") String participants,
			@Param(value=NodeInstance.STATUS, required=false, enumClass=NodeInstanceStatus.class,	desc="状态") Integer status,
			@Param(value=NodeInstance.CREATOR, required=false,	desc="创建人") String creator,
			@Param(value=NodeInstance.CREATE_TIME, required=false,	desc="创建时间") Date create_time
		) throws Exception {
		Principal p = ServiceContext.getContext().getPrincipal();
		return ModelFactory.create(NodeInstance.class, 
				NodeInstance.STATUS, NodeInstanceStatus.PROCESSING.value(),
				NodeInstance.CREATOR, (p == null?null: p.getName()),
				NodeInstance.CREATE_TIME, new Date());
	}

	@MethodInfo("修改")
	@DaoUpdate(entity=NodeInstance.ENTITY_NAME)
	public ActionResult update(
			@Param(value=NodeInstance.NODE_INSTANCE_ID, required=true,	desc="节点实例ID") Long node_instance_id,
			@Param(value=NodeInstance.FLOW_INSTANCE_ID, required=true,	desc="流程实例ID") Long flow_instance_id,
			@Param(value=NodeInstance.NODE_ID, required=true,	desc="节点ID") Long node_id,
			@Param(value=NodeInstance.FLOW_DEF_ID, required=true,	desc="流程定义ID") Long flow_def_id,
			@Param(value=NodeInstance.FLOW_ID, required=true,	desc="流程ID") Long flow_id,
			@Param(value=NodeInstance.NAME, required=true,	desc="名称") String name,
			@Param(value=NodeInstance.REMARKS, required=false,	desc="说明") String remarks,
			
			@Param(value=NodeInstance.PLAN_START, required=false,	desc="计划开始时间") Date plan_start,
			@Param(value=NodeInstance.PLAN_END, required=false,	desc="计划结束时间") Date plan_end,
			@Param(value=NodeInstance.EXPECT_TIME, required=false,	desc="期望完成时间") String expect_time,
			@Param(value=NodeInstance.ACTUAL_START, required=false,	desc="实际开始时间") Date actual_start,
			@Param(value=NodeInstance.ACTUAL_END, required=false,	desc="实际结束时间") Date actual_end,
			@Param(value=NodeInstance.FORM_ACTION, required=false,	desc="表单行为") String form_action,
			@Param(value=NodeInstance.FORM_CODE, required=false,	desc="表单代码") String form_code,
			@Param(value=NodeInstance.FORM_DATA, required=false,	desc="表单数据") String form_data,
			
			@Param(value=NodeInstance.EMERGENCY_LEVEL, required=false,	desc="紧急程度") Integer emergency_level,
			@Param(value=NodeInstance.PRIORITY_LEVEL, required=false,	desc="优先级别") Integer priority_level,
			@Param(value=NodeInstance.PARTICIPANTS, required=false,	desc="执行人") String participants,
			@Param(value=NodeInstance.STATUS, required=false,	desc="状态") Integer status
		) throws Exception {
		
		return null;
	}

	@MethodInfo("修改")
	@DaoUpdate(entity=NodeInstance.ENTITY_NAME)
	public ActionResult start(
			@Param(value=NodeInstance.NODE_INSTANCE_ID, required=true,	desc="节点实例ID") Long node_instance_id,
			
			@Param(value=NodeInstance.STATUS, required=false, enumClass=NodeInstanceStatus.class,	desc="状态") Integer status,
			@Param(value=NodeInstance.ACTUAL_START, required=false,	desc="实际开始时间") Date actual_start,
			@Param(value=NodeInstance.UPDATOR, required=false,	desc="修改人") String updator,
			@Param(value=NodeInstance.UPDATE_TIME, required=false,	desc="修改时间") Date update_time
		) throws Exception {
		Principal p = ServiceContext.getContext().getPrincipal();
		return ModelFactory.create(ActionResult.class, 
				NodeInstance.STATUS, NodeInstanceStatus.PROCESSING.value(),
				NodeInstance.ACTUAL_START, new Date(),
				NodeInstance.UPDATOR, (p == null?null: p.getName()),
				NodeInstance.UPDATE_TIME, new Date());
	}

	@MethodInfo("修改")
	@DaoUpdate(entity=NodeInstance.ENTITY_NAME)
	public ActionResult finish(
			@Param(value=NodeInstance.NODE_INSTANCE_ID, required=true,	desc="节点实例ID") Long node_instance_id,
			@Param(value=NodeInstance.STATUS, required=true, enumClass=NodeInstanceStatus.class,	desc="状态") Integer status,
			@Param(value=NodeInstance.PARTICIPANTS, required=true,	desc="执行人") String participants,
			@Param(value=NodeInstance.FORM_DATA, required=false,	desc="表单数据") String form_data,

			@Param(value=NodeInstance.ACTUAL_END, required=false,	desc="实际结束时间") Date actual_end,
			@Param(value=FlowInstance.CONSUME_SECONDS, required=false,	desc="耗时") Long consume_seconds,
			@Param(value=NodeInstance.UPDATOR, required=false,	desc="修改人") String updator,
			@Param(value=NodeInstance.UPDATE_TIME, required=false,	desc="修改时间") Date update_time
		) throws Exception {
		Principal p = ServiceContext.getContext().getPrincipal();
		return ModelFactory.create(ActionResult.class, 
				NodeInstance.ACTUAL_END, new Date(),
				NodeInstance.UPDATOR, (p == null?null: p.getName()),
				NodeInstance.UPDATE_TIME, new Date());
	}

	@MethodInfo("删除")
	@DaoRemove(entity=NodeInstance.ENTITY_NAME)
	public ActionResult remove(
			@Param(value=NodeInstance.NODE_INSTANCE_ID, required=true,	desc="节点实例ID") Long node_instance_id
		) throws Exception {
		
		return null;
	}

	@MethodInfo("搜索")
	@DaoQuery(entity=NodeInstance.ENTITY_NAME, pageable=false, modelClass=NodeInstance.class, osql="order by actual_end")
	public QueryResult<NodeInstance> findByFlowInstanceId(
			@Param(value=NodeInstance.FLOW_INSTANCE_ID, required=true,	desc="流程实例ID") Long flow_instance_id,
			@Param(value=NodeInstance.STATUS, required=false,	desc="状态", tag="IN") Integer[] status) throws Exception {
		return null;
	}

	@MethodInfo("搜索")
	@DaoQuery(entity=NodeInstance.ENTITY_NAME, pageable=false, modelClass=NodeInstance.class, osql="order by actual_end")
	public QueryResult<NodeInstance> findByFlowInstanceIdAndNodeId(
			@Param(value=NodeInstance.FLOW_INSTANCE_ID, required=true,	desc="流程实例ID") Long flow_instance_id,
			@Param(value=NodeInstance.NODE_ID, required=true,	desc="节点ID") Long node_id) throws Exception {
		return null;
	}

	@MethodInfo("查询")
	@DaoQuery(entity=NodeInstance.ENTITY_NAME, single=true, throwsNotFoundException=true )
	public NodeInstance findById(
			@Param(value=NodeInstance.NODE_INSTANCE_ID, required=true,	desc="节点实例ID") Long node_instance_id
		) throws Exception {
		return null;
	}

}